package com.cjm.one.strategy;

import com.cjm.one.model.coupon.context.CouponContext;
import com.cjm.one.model.coupon.vo.CouponInfoVo;
import com.cjm.one.model.coupon.vo.GoodsDiscountVO;
import com.cjm.one.model.goods.entity.GoodsSku;
import com.cjm.one.model.goods.vo.SkuWithQuantity;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
 * @description: 优惠券策略类，用于计算商品折扣
 * @author: cjm
 * @date: 2025/3/27 23:32
 * @param:
 * @return:
 **/
@Slf4j
public class CouponStrategy {
    public List<GoodsDiscountVO> calculate(CouponContext context) {
        // 创建包含所有可用优惠券的共享券池
        CouponPool couponPool = new CouponPool(
                Stream.of(
                        context.getItemCoupons(),
                        context.getCategoryCoupons(),
                        context.getUniversalCoupons()
                ).flatMap(List::stream).collect(Collectors.toList())
        );

        return context.getSkuWithQuantities().stream()
                .map(sku -> processSku(sku,couponPool)).collect(Collectors.toList());
    }
    private GoodsDiscountVO processSku(SkuWithQuantity skuWithQuantity, CouponPool pool) {
        GoodsDiscountVO vo = new GoodsDiscountVO();
        GoodsSku sku = skuWithQuantity.getSku();
        vo.setSkuId(sku.getId());
        vo.setOriginalPrice(sku.getSalePrice());
        vo.setMarketPrice(sku.getMarketPrice());
        vo.setQuantity(skuWithQuantity.getQuantity());
        // 获取当前SKU可用的所有优惠券（含状态校验）
        List<CouponInfoVo> applicableCoupons = pool.getApplicableCoupons(sku);
        log.info("当前SKU可用的所有优惠券applicableCoupons:{}", applicableCoupons);
        // 找到最佳可用优惠券
        CouponSelection best = findBestCoupon(skuWithQuantity, applicableCoupons);
        if (best != null) {
            applyCoupon(vo, best);
            pool.markUsed(best.getCoupon().getId()); // 标记优惠券已使用
        }
        return vo;
    }




    private CouponSelection findBestCoupon(SkuWithQuantity sku, List<CouponInfoVo> coupons) {
        return coupons.stream()
                .map(c -> new CouponSelection(c, calculateDiscountValue(c, sku.getSku().getSalePrice().multiply(new BigDecimal(sku.getQuantity()))
                        .setScale(2, RoundingMode.HALF_UP))))
                .filter(selection -> selection.getDiscount().compareTo(BigDecimal.ZERO) > 0)
                .max(
                        // 第一优先级：优惠力度从大到小排序
                        Comparator.comparing(CouponSelection::getDiscount)
                                // 第二优先级：优惠券类型优先级从高到低排序
                                .thenComparing(s -> getPriority(s.getCoupon().getRangeType()), Comparator.reverseOrder())
                )
                .orElse(null);
    }

    private int getPriority(Integer rangeType) {
        return switch (rangeType) {
            case 3 -> 3; // 商品券
            case 2 -> 2; // 分类券
            case 1 -> 1; // 通用券
            default -> 0;
        };
    }

    private BigDecimal calculateDiscountValue(CouponInfoVo coupon, BigDecimal price) {
        // 判断是否满足使用门槛
        if (coupon.getConditionAmount().compareTo(BigDecimal.ZERO) !=0 && price.compareTo(coupon.getConditionAmount()) < 0) {
            return BigDecimal.ZERO;
        }
        if (coupon.getCouponType() == 1) { // 现金券
            return coupon.getAmount().min(price);
        } else { // 折扣券
            BigDecimal multiply = price.multiply(BigDecimal.ONE.subtract(
                    coupon.getDiscount().divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP)));
            log.info("discount coupon:{}",multiply);
            return  multiply;
        }
    }
    // 新增优惠应用方法
    private void applyCoupon(GoodsDiscountVO vo, CouponSelection selection) {
        vo.setUsedCoupon(selection.getCoupon());
        vo.setDiscountAmount(selection.getDiscount());
        vo.setFinalPrice(vo.getOriginalPrice().subtract(selection.getDiscount()));
    }


}